#include <iostream>
#include <vector>
#include <string>

using namespace std;
/**
 * @brief 产品
 *
 */
class House {
public:
    House() {
    }
    void show() {
        cout << "This is your house:\n";
        for (auto p : parts) {
            cout << p << ", ";
        }
        cout << endl;
    }
    vector<string> parts{};
};

/**
 * @brief 生成器、建造者
 *
 */
class HouseBuilder {
public:
    virtual ~HouseBuilder() {
        cout << "~HouseBuilder" << endl;
        delete _house;
    }

    virtual void build_main()   = 0;
    virtual void build_garage() = 0;
    virtual void build_pool()   = 0;
    virtual void build_garden() = 0;

    House *get_house() {
        return _house;
    }

protected:
    House *_house;
};

class ChinaHouserBuilder : public HouseBuilder {
public:
    ChinaHouserBuilder() {
        _house = new House();
    }
    ~ChinaHouserBuilder() {
        // cout << "~ChinaHouserBuilder" << endl;
    }
    virtual void build_main() override {
        _house->parts.push_back("chinese main building");
    }
    virtual void build_garage() override {
        _house->parts.push_back("chinese garage");
    }
    virtual void build_pool() override {
        _house->parts.push_back("chinese pool");
    }
    virtual void build_garden() override {
        _house->parts.push_back("chinese garden");
    }
};

class WesternHouserBuilder : public HouseBuilder {
public:
    WesternHouserBuilder() {
        _house = new House();
    }
    ~WesternHouserBuilder() {
        // cout << "~WesternHouserBuilder" << endl;
    }
    virtual void build_main() override {
        _house->parts.push_back("western main building");
    }
    virtual void build_garage() override {
        _house->parts.push_back("western garage");
    }
    virtual void build_pool() override {
        _house->parts.push_back("western pool");
    }
    virtual void build_garden() override {
        _house->parts.push_back("western garden");
    }
};

/**
 * @brief 主管
 * 客户可以委托主管负责管理，让主管与建造者直接沟通
 *
 */
class Director {
public:
    Director(HouseBuilder *builder) :
        _builder(builder) {
    }
    void set_builder(HouseBuilder *builder) {
        _builder = builder;
    }

    void build_simple() {
        _builder->build_main();
    }
    void build_middle() {
        _builder->build_main();
        _builder->build_garage();
    }

private:
    HouseBuilder *_builder;
};

void client() {
    HouseBuilder *builder;
    Director     *director;
    House        *house;

    //
    builder  = new ChinaHouserBuilder();
    director = new Director(builder);

    director->build_simple();
    house = builder->get_house();
    house->show();
    //
    delete builder;
    builder = new WesternHouserBuilder();
    director->set_builder(builder);
    director->build_middle();
    house->show();
}

int main(int argc, char *argv[]) {
    client();
    return 0;
}